﻿/**************************************************************
 @Name : jQuery-vdform (2.0 Alpha版)
 @author: 红叶
 @date: 2012-12-6
 @QQ: 237420759
 @blog: www.vdform.com 
 @desc: 
 *************************************************************/ 
(function ($){
	//获取js的路径
	var js = document.scripts, jsPath = js[js.length - 1].src;
	var jsPath=jsPath.substring(0,jsPath.lastIndexOf("/")+1);
	if(jsPath.substring(0,8)=="file:///"){			   		   //针对chrome获取路径包含file的问题做修正
		jsPath=jsPath.substring(8);
	}
	
	var common ={
		trim : function(str){ //去除空格
			return str.replace(/(^\s*)|(\s*$)/g, "");
		},
		strlen : function (str){ //获取字符长度
			var Charset = jQuery.browser.msie ?document.charset : document.characterSet
			if(Charset.toLowerCase() == 'utf-8'){
				return str.replace(/[\u4e00-\u9fa5]/g, "***").length;
			} else {
				return str.replace(/[^\x00-\xff]/g, "**").length;
			}
		}
	};
	
	
	var vdform = function(form,settings){						//vdform
		var settings=$.extend({},vdform.config,settings);	    //合并整个配置
		var form=jQuery(form);									//获得表单对象
		var elements = form.find('input[validata-options]');	//获取需要校验的元素集合
		//加载主题准备
		if(settings.theme==""){ 								//theme不能为空						
			alert('theme不能为空,请设置theme的值');
			return;
		}
		
		var themeurl;
		if(jsPath.substring(jsPath.length-3)=="js/"){			//只保留到根目录
			themeurl=jsPath.substring(0,jsPath.lastIndexOf("/") -2);
		}else{
			themeurl=jsPath;
		}
	
		//加载主题
		$.ajax({async:false,type: "GET",url:themeurl+"themes/"+settings.theme+"/js/theme.js",dataType: "script",
			error :function(){
				alert('主题加载失败，请确认主题名为【'+settings.theme+'】的是否存在');
			}
		}); 
		
		//加载主题样式
		document.write('\n' + '<link rel="stylesheet" type="text/css" href="'+ themeurl+'themes/'+settings.theme+'/style/style.css" />');
		
		
		//注册校验事件
		elements.keyup(function(index){							//按下键盘
			return vdform.check(jQuery(this));
		});
		
		elements.blur(function(index){						   //失去焦点时验证
			return vdform.check(jQuery(this));
		});
		
		elements.change(function(index){					  //内容改变时验证
			return vdform.check(jQuery(this));
		});
		
		form.submit(function(){								  //当form表单提交的时候验证
			var isValid = true;
			var errIndex= new Array();
			var n=0;
			elements.each(function(i){
				//校验是否失败
				if(vdform.check(jQuery(this))==false){
					isValid  = false;
					errIndex[n++]=i;
				};
			});
			
			//如果校验返回失败焦点与提示信息
			if(isValid==false){
				elements.eq(errIndex[0]).focus().select();
				return false;
			}
			return true;
		});	
	};
	
	
	
	vdform.config = { //默认配置
			theme:"default",                     //风格
			mode : "alert",					     //提示模式(Tip,alert)
			onSuccess : function(){return true}, //提交成功后的回调函数
			onError : function(){return false}	 //提交失败后的回调函数
	};
	
	vdform.validator={ //校验元素 
		dataTypes : "",
		Require : /[^(^\s*)|(\s*$)]/,
	    Email : /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
		Phone : /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/,
		Mobile : /^((\(\d{3}\))|(\d{3}\-))?13[0-9]\d{8}?$|15[89]\d{8}?$/,
		Tel: /^(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/,
	    Call:/^(^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$)|(^(1[358]\d{9})$)/,
	    Url : /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/,
	    IdCard : "this.validator.isIdCard(value)",
	    Currency : /^\d+(\.\d+)?$/,
	    Number : /^\d+$/,
	    Zip : /^[1-9]\d{5}$/,
	    QQ : /^[1-9]\d{4,8}$/,
		IP  : /^[\d\.]{7,15}$/,
		Integer : /^[-\+]?\d+$/,
	    ZInteger: /^[+]?\d+$/,
	    Double : /^[-\+]?\d+(\.\d+)?$/,
	    ZDouble: /^[+]?\d+(\.\d+)?$/,
	    English : /^[A-Za-z]+$/,
	    Chinese :  /^[\u0391-\uFFE5]{2,6}$/,
	    Username : /^[a-z]\w{3,}$/i,
	    UnSafe : /^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\"]*)|.{0,5})$|\s/,
	    IsSafe : function(str){return !this.UnSafe.test(str); },
	    SafeString : "this.validator.IsSafe(value)",
	    Filter : "this.validator.doFilter(value)",
	    Limit : "this.validator.checkLimit(common.strlen(value))",
	    LimitB : "this.validator.checkLimit(this.validator.LenB(value))",
	    Date : "this.validator.isDate(value)",
	    Repeat : "this.validator.checkRepeat(value)",
	    Range : "this.validator.checkRange(value)",
	    Compare : "this.validator.checkCompare(value)",
	    Custom : "this.validator.Exec(value)",
	    Group : "this.validator.mustChecked()",
		Ajax: "this.validator.doajax(errindex)",
		ErrorItem : [document.forms[0]],
 		ErrorMessage : ["以下原因导致提交失败：\t\t\t\t"],
		
		//身份证号校验
		isIdCard : function(number){
		var area={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏",33:"浙江",
		34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",
		52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"};
		var idcard, Y, JYM;
		var S, M;
		var idcard_array = new Array();
		idcard_array = number.split("");
		//地区检验
		if (area[parseInt(number.substr(0, 2))] == null) return false;
		//身份号码位数及格式检验
		switch (number.length) {
		case 15:
			if ((parseInt(number.substr(6, 2)) + 1900) % 4 == 0 || ((parseInt(number.substr(6, 2)) + 1900) % 100 == 0
				&& (parseInt(number.substr(6, 2)) + 1900) % 4 == 0)) {
				//测试出生日期的合法性
				ereg = /^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/;				
			} else {
				//测试出生日期的合法性
				ereg = /^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/; 
			}
			if (ereg.test(number)) {
				return true;
			} else{
				return false;
			}
			break;
		case 18:
			/*18位身份号码检测
			出生日期的合法性检查
			闰年月:
			((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
			平年月日:
			((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))*/
			if (parseInt(number.substr(6, 4)) % 4 == 0 || (parseInt(number.substr(6, 4)) % 100 == 0 
				&& parseInt(number.substr(6, 4)) % 4 == 0)) {
				//闰年出生日期的合法性正则表达式
				ereg = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$/; 
			} else {
				//平年出生日期的合法性正则表达式
				ereg = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$/; 
			}
			//测试出生日期的合法性
			if (ereg.test(number)) { 
				//计算校验位
				S = (parseInt(idcard_array[0]) + parseInt(idcard_array[10])) * 7 + (parseInt(idcard_array[1])
				  + parseInt(  idcard_array[11])) * 9 + (parseInt(idcard_array[2]) + parseInt(idcard_array[12])) * 10 
				  + (parseInt(idcard_array[3]) + parseInt(idcard_array[13])) * 5 + (parseInt(idcard_array[4]) 
				  + parseInt(idcard_array[14])) * 8 + (parseInt(idcard_array[5]) + parseInt(idcard_array[15])) * 4 
				  + (parseInt(idcard_array[6]) + parseInt(idcard_array[16])) * 2 + parseInt(idcard_array[7]) * 1 
				  + parseInt(idcard_array[8]) * 6 + parseInt(idcard_array[9]) * 3;
				Y = S % 11;
				M = "F";
				JYM = "10X98765432";
				M = JYM.substr(Y, 1); //判断校验位
				if (M == idcard_array[17]) return true; //检测ID的校验位
				else return false;	
			} else return false;
			break;
			default:
				return false;
			break;
		 }
		},//end isIdCard
	
		isDate : function(op){
			var formatString=this['dataTypes'].format;
			formatString = formatString || "ymd";
			var m, year, month, day;
			switch(formatString){
			case "ymd" :
				m = op.match(new RegExp("^((\\d{4})|(\\d{2}))([-./])(\\d{1,2})\\4(\\d{1,2})$"));
				if(m == null ) return false;
				day = m[6];
				month = m[5]*1;
				year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10));
			break;
			case "dmy" :
				m = op.match(new RegExp("^(\\d{1,2})([-./])(\\d{1,2})\\2((\\d{4})|(\\d{2}))$"));
				if(m == null ) return false;
				day = m[1];
				month = m[3]*1;
				year = (m[5].length == 4) ? m[5] : GetFullYear(parseInt(m[6], 10));
			break;
			default :
				break;
			}
			if(!parseInt(month)) return false;
			month = month==0 ?12:month;
			var date = new Date(year, month-1, day);
			return (typeof(date) == "object" && year == date.getFullYear() && month == (date.getMonth()+1) && day == date.getDate());
			function GetFullYear(y){
				return ((y<30 ? "20" : "19") + y)|0;
			}
		}, //end isDate
		
		doFilter : function(value){
			var filter=this['dataTypes'].accept;
			return new RegExp("^.+\.(?=EXT)(EXT)$".replace(/EXT/g,filter.split(/\s*,\s*/).join("|")),"gi").test(value);
		},//end doFilter
	
		checkLimit:function(len){
			var minval=this['dataTypes'].min || Number.MIN_VALUE;
			var maxval=this['dataTypes'].max || Number.MIN_VALUE;
			return (minval<= len && len<=maxval);
	
		},//end checkLimit
	
		LenB : function(str){
			return str.replace(/[^\x00-\xff]/g,"**").length;
		},//end LenB
	
		checkRepeat:function(value){
			var to=this['dataTypes'].to;
			var toval=jQuery('input[name="'+to+'"]').eq(0).val();
			var element = this['element'];
			var str_errmsg=this['dataTypes'].msg; //获取提示信息
			if((toval == "undefined" || toval == "")&&(value =="")){
				 return false;
			}
			return value==toval;
		},//end checkRepeat
	
		checkRange : function(value){
			value = value|0;
			var minval=this['dataTypes'].min || Number.MIN_VALUE;
			var maxval=this['dataTypes'].max || Number.MAX_VALUE;
			return (minval<=value && value<=maxval);
		},//end checkRange
	
		checkCompare : function(value){
			var compare=this['dataTypes'].compare;
			if(isNaN(value)) return false;
			value = parseInt(value);
			return eval(value+compare);
		},//end checkCompare
	
		Exec : function(value){
			var reg =this['dataTypes'].regexp;
			return new RegExp(reg,"gi").test(value);
		},//end Exec
	
		mustChecked : function(){
			var tagName=vdform['element'].attr('name');
			var f=vdform['element'].parents('form');
			var v=f.find('input[name="'+tagName+'"]');
			var n=f.find('input[name="'+tagName+'"]:checked').length;
			var count = f.find('input[name="'+tagName+'"]').length;
			var minval=this['dataTypes'].min || 1;
			var maxval=this['dataTypes'].max || count;
			return (minval<=n && n<=maxval);
		},//end mustChecked
		
		doajax : function(value) {	
			var element = vdform['element'];
			var errindex = vdform['errindex'];
			var val = element.val(); //获取元素的值
			var url=this['dataTypes'].url;
			var str_errmsg=this['dataTypes'].msg; //获取提示信息
			var arr_errmsg ; //错误信息数组
			var errmsg ;     //错误信息
			arr_errmsg= str_errmsg.split('|') ;
			errmsg = arr_errmsg[errindex] ;
			var type=vdform['element'].attr('type');  //获取元素类型
			var Charset = jQuery.browser.msie ? document.charset : document.characterSet;
			var methodtype = (Charset.toLowerCase() == 'utf-8') ? 'post' : 'get';
			var method=this['dataTypes'].method || methodtype;
			var name = vdform['element'].attr('name');
			if(url=="" || url==undefined) {
				 var msg='请设定url的值';
				 return  vdform.showTipAjaxMsg(element,msg,false);
			}
			if(url.indexOf('?')>-1){
		 		 url = url+"&"+name+"="+escape(val);
			} else {
				 url = url+'?'+name+"="+escape(val);
			}
			
			var s = $.ajax({
				type: method,
				url: url,
				data: {},
				cache: false,
				async: false,
				success: function(data){
					data = data.replace(/(^\s*)|(\s*$)/g, "");
					   if(data != 'success'){
						  errmsg = errmsg=="" ? data : errmsg;
						  return  vdform.showTipAjaxMsg(element,errmsg,false);
					   }
				   }
			 }).responseText;
			 s = s.replace(/(^\s*)|(\s*$)/g, "");
			 return s == 'success' ? true : false;
		}//end doajaxs
	};
	
	vdform.check=function(obj){
		var isValid=new Array();
		var valiData = $.trim(obj.attr('validata-options'));
		vdform.validator['dataTypes']=eval("({"+valiData+"})");
		var dataTypes=vdform.validator['dataTypes'];
		var value = $.trim(obj.val()); //去除值的空格
		vdform.resetTipMsg(obj);//移除错误信息
		
		//默认required为true
		if(typeof(dataTypes.required) == "undefined"){
			dataTypes.required=true;
		}
		
		//如果requierd为fales并且没有值则不做校验
		if(!dataTypes.required && value==""){return true};
		
		var validType = dataTypes.validType.split('|');
		
		//遍历validType
		jQuery.each(validType,function(index,type){
			if(typeof(vdform.validator[type]) == "undefined") {
				isValid[index]=false;
			}
			if(vdform.checkDataType(obj,type)){
				isValid[index]=true;
			}else{
				isValid[index]=false;
			}
			//Tip方式显示信息
			vdform.showTipMsg(obj,index,isValid[index]);
			return isValid[index];
		});
	}
	
	//检测校验类型
	vdform.checkDataType= function(element,datatype){
		var value=jQuery.trim(element.val());
		this['element'] = element;
		switch(datatype){
			 case "IdCard" :
			 case "Date" :
			 case "Repeat" :
			 case "Range" :
			 case "Compare" :
			 case "Custom" :
			 case "Group" : 
			 case "Limit" :
			 case "LimitB" :
			 case "SafeString" :
			 case "Filter" :
			 	return eval(vdform.validator[datatype]);
			 break;
			 default:
			 	return vdform.validator[datatype].test(value);
			 break;
		}
	}
	
	
	vdform.showTipMsg=function(element,index,isSuccess){ //显示信息
		var msg=vdform.validator['dataTypes'].msg;
		var str_tipmsg=typeof(msg) == "undefined" ? 'unkonwn': msg;
		var arr_tipmsg = str_tipmsg.split('|');
		var tipmsg = arr_tipmsg[index] ? arr_tipmsg[index]: arr_tipmsg[0];
		var offset=element.offset(); 											//获取元素位置
		if($.browser.msie){ 
			var top=offset.top-offsetIETop;
			var left=offset.left+element.width()+offsetIELeft;
		}else{
			var top=offset.top-offsetChromeTop;
			var left=offset.left+element.width()+offsetChromeLeft;
		}
	
		vdform.resetTipMsg(element);//移除错误信息
		if(isSuccess){
			html=onSuccessHtml;
			element.removeClass(onErrorInputClass);
			tipmsg="校验成功"
		}else{
			html=onErrorHtml;
			element.addClass(onErrorInputClass);
		}
		var msgtip= jQuery(html.replace(/\$data\$/g, tipmsg));
		msgtip.css("top", top+"px").css("left", left+"px");
		msgtip.insertAfter(element);
	}
	

	vdform.showTipAjaxMsg=function(element,tipmsg,isSuccess){ 	//显示Ajax校验信息
		var offset=element.offset(); 											//获取元素位置
		if($.browser.msie){ 
			var top=offset.top-offsetIETop;
			var left=offset.left+element.width()+offsetIELeft;
		}else{
			var top=offset.top-offsetChromeTop;
			var left=offset.left+element.width()+offsetChromeLeft;
		}
		vdform.resetTipMsg(element);//移除错误信息
		if(isSuccess){
			html=onSuccessHtml;
			element.removeClass(onErrorInputClass);
		}else{
			html=onErrorHtml;
			element.addClass(onErrorInputClass);
		}
		var msgtip= jQuery(html.replace(/\$data\$/g, tipmsg));
		msgtip.css("top", top+"px").css("left", left+"px");
		msgtip.insertAfter(element);
	}

	vdform.resetTipMsg=function(element){ //重置提示信息
		element.removeClass(onErrorInputClass);
		element.next().remove();
	}
	
	$.fn.vdform=function(settings){
		return new vdform(this,settings);
	};
	
})(jQuery);